package net.sourceforge.stripes.authentication;

import net.sourceforge.stripes.authentication.util.QuotedStringTokenizer;

import javax.servlet.http.HttpServletRequest;

// TODO This is far from perfect. Check the RFC. I think we do something wrong with the checking of the nonce for example.

public class DigestAuthenticationChecker extends AbstractAuthenticationChecker
{
    public AuthenticatedUserInfo check(AuthenticationService authenticationService, HttpServletRequest request, String credentials) throws Exception
    {
        AuthenticatedUserInfo result = null;

        if (credentials.startsWith("Digest ") || credentials.startsWith("digest "))
        {
            DigestCredentials digest = new DigestCredentials(request.getMethod());

            // Parse the credentials

            QuotedStringTokenizer tokenizer = new QuotedStringTokenizer(credentials, "=, ", true, false);

            String last = null;
            String name = null;

            while (tokenizer.hasMoreTokens()) {
                String tok = tokenizer.nextToken();
                char c = (tok.length() == 1) ? tok.charAt(0) : '\0';

                switch (c) {
                    case'=':
                        name = last;
                        last = tok;
                        break;
                    case',':
                        name = null;
                    case' ':
                        break;

                    default:
                        last = tok;
                        if (name != null) {
                            if ("username".equalsIgnoreCase(name))
                                digest.username = tok;
                            else if ("realm".equalsIgnoreCase(name))
                                digest.realm = tok;
                            else if ("nonce".equalsIgnoreCase(name))
                                digest.nonce = tok;
                            else if ("nc".equalsIgnoreCase(name))
                                digest.nc = tok;
                            else if ("cnonce".equalsIgnoreCase(name))
                                digest.cnonce = tok;
                            else if ("qop".equalsIgnoreCase(name))
                                digest.qop = tok;
                            else if ("uri".equalsIgnoreCase(name))
                                digest.uri = tok;
                            else if ("response".equalsIgnoreCase(name))
                                digest.response = tok;
                            break;
                        }
                }
            }

            //

            AuthenticatedUserInfo authenticatedUserInfo = authenticationService.getAuthenticatedUserInfo(digest.username);
            if (authenticatedUserInfo != null && digest.check(authenticatedUserInfo.getHashedPassword())) {
                result = authenticatedUserInfo;
            }
        }

        return result;
    }
}
